/**************************************************************************
 * @doc TRAN
 * @module SETTLE.C |
 * Source file for the Settlement functions.
 *
 * Product     :   SoftPay 2000 (Global Payment Methodology).
 * <nl>Developer   :   SoftPay Development Team (I_SP2000).
 * <nl>Notes       :
 *
 * @head3 TRAN |
 * @index | TRAN
 * @end
 *
 * Copyright (c) 1996-2000 by VeriFone Inc. All rights reserved.
 *
 * No part of this software may be used, stored, compiled, reproduced,
 * modified, transcribed, translated, transmitted, or transferred, in any form
 * or by any means whether electronic, mechanical, magnetic, optical,
 * or otherwise, without the express prior written permission of VeriFone, Inc.
 *
 * Revision History
 * ------------------------------------------------------------------------
$Log: /SoftPay/SPK2SIM/Source/Tran/settle.c $
 ********************************************************************************/

#include <project.h>

#ifdef BATCH_DEFINED
#define VSSETL_C

//#include <beetle.h>
//#include <beetleplug.h>

#include <message.h>
#include <applidl.h>
#include <aclconio.h>
#include <acldev.h>
#include <aclstr.h>
#include <stdlib.h>
#include <string.h>
#include <actutil.h>

/** /#define DEBUG_VSSETTLE*/
#ifdef DEBUG_VSSETTLE
#define DEBUG_95
#endif

#include <define.h>
#include <transact.h>
#include <settle.h>
#include <settlbat.h>
#include <gds.h>
#include <accum.h>
#include <date.h>
#include <ui.h>
#include <msg.h>
#include <mdlfuncs.h>
#include <msgfuncs.h>
#include <bdt.h>
#include <cst.h>
#include <hdt.h>
#include <tblutil.h>
#include <lct.h>
#include <mht.h>
#include <mit.h>
#include <sdt.h>
#include <tct.h>
#include <report.h>
#include <init.h>
#include <oper.h>
#include <spdebug.h>
#include <pbatch.h>
#include <menufunc.h>
#include <tran.h>

#include <udt.h>
#include <msgclrk.h>
#include <msgshf.h>
#include <rcptsegs.h>
#include <rcptcmpt.h>
#include <pct.h>
#include <amount.h>
#include <codesec.h>

/*********************************************************************************************
* @func int | inConfirmSettle |
*       Confirm the Settlement totals
*
* @parm TRANSACTION_OBJECT * | pobTran |
*       Transaction object.
*
* @rdesc return values.
* @flag int    |  VS_ERR
* @flag int    |  VS_SUCCESS
* @end
**********************************************************************************************/

int inConfirmSettle(TRANSACTION_OBJECT* pobTran) {
    ACCUM_REC srHostTotals;
    int inSettleType,
    inChar,
    inResult = VS_SUCCESS;
    double dbSalesTotal,
    dbRefundsTotal;
    char szAmt[AMT_SIZE + 1];
    char szSalesAmt[AMT_SIZE + 1];
    char szRefundsAmt[AMT_SIZE + 1];
    char szTotalAmt[AMT_SIZE + 1];
    char* szDisplaySymbol;
    char szMsg[MESSAGE_SIZE + 1];
    char szDisplayBuffer[DISP_STR_LEN + 1];

    if (inGetHostTotals(pobTran, &srHostTotals) != VS_SUCCESS)
        return (VS_ERR);
    if (fGGAutoSettle())
        return (VS_SUCCESS);

    /* added for single batch */
    if (inGetHostTranCnt(pobTran) == 0)
        return (VS_SUCCESS);

    inSettleType = inGetSettlementType();
    if (inSettleType > 3)                         /* invalid settlement type */
        return (VS_ERR);

    dbSalesTotal = srHostTotals.srTotals[CREDIT_CARD].dbAmount[DEBIT_TRAN] + srHostTotals.srTotals[DEBIT_CARD].dbAmount[DEBIT_TRAN];
    dbRefundsTotal = srHostTotals.srTotals[CREDIT_CARD].dbAmount[CREDIT_TRAN] + srHostTotals.srTotals[DEBIT_CARD].dbAmount[CREDIT_TRAN];

    szSalesAmt[0] = '\0';
    vdDb2Str(dbSalesTotal, szSalesAmt);

    //          sprintf(szSalesAmt, SUBSTITUTE_LD, lnSalesTotal);

    szRefundsAmt[0] = '\0';
    vdDb2Str(dbRefundsTotal, szRefundsAmt);

    //            sprintf(szRefundsAmt, SUBSTITUTE_LD, lnRefundsTotal);

    szTotalAmt[0] = '\0';
    vdDb2Str((dbSalesTotal - dbRefundsTotal), szTotalAmt);

    //sprintf(szTotalAmt, SUBSTITUTE_LD, lnSalesTotal - lnRefundsTotal);


    if (inSettleType == CONFIRM_SETTLE_TOTALS)      /* confirm totals */ {
        inChar = 0;
        if (obDisp.inCharsPerColumn >= 3) {
            vdDispFormattedAmt(szSalesAmt, SALES_AMT_MSG, obDisp.inTopEntryRow);
            vdDispFormattedAmt(szRefundsAmt, REFUNDS_AMT_MSG, obDisp.inTopEntryRow + 1);
            vdDispFormattedAmt(szTotalAmt, TOTALAMT_MSG9, obDisp.inTopEntryRow + 3);
            vdGetMessageFromFile(O3200_ENTER_CONFIRM, szMsg);
            vdDisplayAt(obDisp.inHomeCol, obDisp.inCharsPerColumn, szMsg, CLR_EOL);
            do {
                inChar = inWaitKey(inGetIdleTimeOut());
            } while ((inChar != KEY_CR) && (inChar != KEY_CANCEL)); // BJD: KEY_CLR -> KEY_CANCEL

        }

        if (inChar == KEY_CANCEL) // BJD: KEY_CLR -> KEY_CANCEL
        {
            vdSGErrorMessage(TXN_CANCELLED);
            return (VS_ERR);
        }
    } else {
        if (inSettleType == ENTER_SETTLE_TOTALS)      /* enter totals */ {
            szDisplaySymbol = szGetCurSymbol();
            inResult = VS_ERR;
            vdDisplayMessageFromFile(SALES_AMT_MSG, ENTRY_MSG);

            do {
                // We have a problem here with regards to Large amounts - sadiq.
                szAmt[0] = '\0';
                vdClearStatusMessage();
                vdGetMessageFromFile(SALES_AMT_MSG, szDisplayBuffer);
                //       BT_TRACE ('I', szDisplayBuffer);
                if ((inResult = inGetAmount(szAmt, VS_TRUE, 0L, 999999999L, szDisplaySymbol)) == VS_SUCCESS)
                    if (atol(szAmt) == (long) dbSalesTotal)
                        inResult = VS_SUCCESS;
                    else {
                        vdDisplayMessageFromFile(TOTALS_MISMATCH_MSG, ERROR_MSG);
                        inResult = VS_ERR;
                    }
                else
                    return(VS_ESCAPE);
                if (act_kbd_pending_test(KEY_CANCEL))
                    return(VS_ESCAPE);
            } while (inResult == VS_ERR);

            inResult = VS_ERR;

            vdDisplayMessageFromFile(REFUNDS_AMT_MSG, ENTRY_MSG);

            do {
                szAmt[0] = '\0';
                vdClearStatusMessage();

                vdGetMessageFromFile(REFUNDS_AMT_MSG, szDisplayBuffer);
                //             BT_TRACE ('I', szDisplayBuffer);
                if ((inResult = inGetAmount(szAmt, VS_TRUE, 0L, 999999999L, szDisplaySymbol)) == VS_SUCCESS)
                    if (atol(szAmt) == (long) dbRefundsTotal)
                        inResult = VS_SUCCESS;
                    else {
                        vdDisplayMessageFromFile(TOTALS_MISMATCH_MSG, ERROR_MSG);
                        inResult = VS_ERR;
                    }
                else
                    return(VS_ESCAPE);
                if (act_kbd_pending_test(KEY_CANCEL))
                    return(VS_ESCAPE);
            } while (inResult == VS_ERR);

            inResult = VS_ERR;

            vdDisplayMessageFromFile(TOTALAMT_MSG9, ENTRY_MSG);
            do {
                szAmt[0] = '\0';
                vdClearStatusMessage();
                // We have a problem here with regards to Large amounts - sadiq.
                if ((inResult = inGetAmount(szAmt, VS_TRUE, -999999999L, 999999999L, szDisplaySymbol)) == VS_SUCCESS)
                    if (atol(szAmt) == (long) abs((int) (dbSalesTotal - dbRefundsTotal)))
                        inResult = VS_SUCCESS;
                    else {
                        vdDisplayMessageFromFile(TOTALS_MISMATCH_MSG, ERROR_MSG);
                        inResult = VS_ERR;
                    }
                else
                    return(VS_ESCAPE);
                if (act_kbd_pending_test(KEY_CANCEL))
                    return(VS_ESCAPE);
            } while (inResult == VS_ERR);
        }
    }
    return(inResult);
}

/*********************************************************************************************
* @func int | inCloseBatchOper |
*       Prints a totals report and clears the batch (no comm)
*
* @parm TRANSACTION_OBJECT * | pobTran |
*       Transaction object.
*
* @rdesc return values.
* @flag int    |  VS_ERR
* @flag int    |  VS_SUCCESS
* @end
**********************************************************************************************/

int inCloseBatchOper(TRANSACTION_OBJECT* pobTran) {
    int inResult;

    inGetReport1Template();

    if ((inResult = inPrintSettlementReport(pobTran, VS_FALSE, VS_TRUE, VS_TRUE)) != VS_SUCCESS)
        return(inResult);

    if ((inResult = inResetBatch(pobTran)) == VS_SUCCESS) {
        if ((inResult = inResetAccum()) != VS_SUCCESS) {
            vdDisplayMessageFromFile(ACCUM_ERR_MSG, ERROR_MSG);
            return(inResult);
        }
#ifdef CLERK_DEFINED
        if ((inResult = inResetUTT(pobTran)) != VS_SUCCESS)
            vdDisplayMessageFromFile(UTT_FAIL_ERR_MSG21, ERROR_MSG);
        #endif

        /* Zero the STT File */
#ifdef SHIFT_DEFINED
        if (inResetSTT(pobTran) != VS_SUCCESS)
            vdDisplayMessageFromFile(STT_FAIL_ERR_MSG21, ERROR_MSG);

#endif
    }
    return(inResult);
}

/*********************************************************************************************
* @func long | lnProceedWithSettlement |
*       Verifies that the batch is not empty
*
* @parm TRANSACTION_OBJECT * | pobTran |
*       Transaction object.
*
* @rdesc return values.
* @flag int    |  VS_ERR
* @flag int    |  VS_SUCCESS
* @end
**********************************************************************************************/

long lnProceedWithSettlement(TRANSACTION_OBJECT* pobTran) {
    //pdebug(("--lnProceedWithSettlement--"));
    if (inGetHostTranCnt(pobTran) < 1)
        return(BATCH_EMPTY_MSG);
    else
        return (VS_SUCCESS);
}

/*********************************************************************************************
* @func void | vdMustSettleHostFlags |
*       Sets the host must settle flag
*
* @parm VS_BOOL | fSettleFlag |
*       Settle Flag (0 or 1).
*
* @end
**********************************************************************************************/

void vdMustSettleHostFlags(VS_BOOL fSettleFlag) {
    vdSetMustSettleFlag(fSettleFlag);
}

/*********************************************************************************************
* @func int | inReprintSettlementReportOperation |
*       Operation flow function which reprints the settlement reports
*
* @parm TRANSACTION_OBJECT * | pobTran |
*       Transaction object.
*
* @rdesc return values.
* @flag int    |  VS_ERR
* @flag int    |  VS_SUCCESS
* @end
**********************************************************************************************/

int inReprintSettlementReportOperation(TRANSACTION_OBJECT* pobTran) {
    char szLocSettDate[DATE_SIZE + 1];
    int inHostIndex;

    //pdebug(("--inReprintSettlementReportOperation--"));

    strcpy(szLocSettDate, pobTran->szSettDate);

    if (inGetPrinterType() == NOPRINTER && fGetEnablePrinter()) {
        vdDisplayMessageFromFile(NO_PRINTER_MSG, WARNING_MSG);
        return(VS_SUCCESS);
    }
    if (!fGetEnablePrinter())
        return(VS_SUCCESS);

    inGetReport1Template();

    /* print batch history for all hosts */
    for (inHostIndex = 0; inHostIndex < MAX_HOSTS; inHostIndex++) {
        strcpy(pobTran->szSettDate, szLocSettDate);

        //      vdSetHostHandle(inHostIndex);

        /* if MIT record not already loaded, load first merchant record */
        if (inGetMerchantNum() == 0)
            inLoadMITRec(0);

        if (inLoadDefaultHost(inHostIndex) != VS_SUCCESS)
            return (VS_ERR);

        if (inLoadDefaultCurrency(pobTran) != VS_SUCCESS)
            return (VS_ERR);

        inReprintSettlRep(pobTran);
    } /* host loop */

    return (VS_SUCCESS);
}

/*********************************************************************************************
* @func int | inRePrintSettlementReport|
*       Form flow function which Browes through the batch and
*       prints the settlement report
*
* @parm TRANSACTION_OBJECT * | pobTran |
*       Transaction object.
*
* @rdesc return values.
* @flag int    |  VS_ERR
* @flag int    |  VS_SUCCESS
* @end
**********************************************************************************************/

int inRePrintSettlementReport(TRANSACTION_OBJECT* pobTran) {
    char szDate[DATE_SIZE + 1];
    long lnRecNum,
    lnRecCnt;
    SETT_REC srLocSRec;
    SETT_KEY srLocSKey;

    strcpy(srRcpt.szHostName, szGetHostName());

    strcpy(szDate, pobTran->szSettDate);

    if (szDate[0] == '\0' && pobTran->szBatchNum[0] == '\0') {
        lnRecCnt = lnGetSettRecCnt();

        if (lnRecCnt == 0L) {
            vdDisplayNoDataMsg();
            return(VS_SUCCESS);
        }

        /* get all records for host and print   */
        for (lnRecNum = 0L; lnRecNum < lnRecCnt; lnRecNum++) {
            if (inLoadSettRec(pobTran, &srLocSRec, &srLocSKey, lnRecNum) == VS_SUCCESS) {
                strlcpy(pobTran->szSettDate, &srLocSRec.szDate[4], 2);
                strlcpy(&pobTran->szSettDate[2], srLocSRec.szDate, 4);
                strlcpy(pobTran->szSettTime, srLocSRec.szTime, 6);
                vdLoadDateTime(pobTran);
                strcpy(srRcpt.szBatchNum, srLocSRec.szBatchNum);
                pad(srRcpt.szBatchNum, srRcpt.szBatchNum, '0', inGetBatchNumSize(), RIGHT);
                strcpy(srRcpt.szStatusMessage, srLocSRec.szSettleResp);
                vdFormatSettleStatusMsg(srRcpt.szStatusMessage);

                if (lnRecNum == 0L)
                    inPrintReceiptHeader(pobTran);
                else
                    lnMiddleCondition &= 0xEFFFFFFF;    /* Do not print report title but once   */
                if (lnRecNum == lnRecCnt - 1)
                    lnMiddleCondition |= 0x04000000;    /* Eject paper after print */
                if (inPrintLines(&obPrinter, SETTLE_TOP_START, SETTLE_BOTTOM_END, NO_BL_LINE, lnMiddleCondition) != VS_SUCCESS)
                    return(VS_ERR);
            } else {
                if (lnRecNum == 0L) {
                    vdDisplayNoDataMsg();
                    return(VS_SUCCESS);
                }
                break;          /* no more records  */
            }
        }
    } else {
        if (szDate[0] != '\0') {
            if (inGetDateSettRec(pobTran, &srLocSRec, &srLocSKey, &lnRecNum) != VS_SUCCESS) {
                vdDisplayNoDataMsg();
                vdSGErrorMessage(0L); /* Clear the error buffer */
                return(VS_SUCCESS);
            }
            strlcpy(pobTran->szSettDate, &srLocSRec.szDate[4], 2);
            strlcpy(&pobTran->szSettDate[2], srLocSRec.szDate, 4);
            strlcpy(pobTran->szSettTime, srLocSRec.szTime, 6);
            vdLoadDateTime(pobTran);
            strcpy(srRcpt.szBatchNum, srLocSRec.szBatchNum);
            pad(srRcpt.szBatchNum, srRcpt.szBatchNum, '0', inGetBatchNumSize(), RIGHT);
            // Load Settle Response Message.
            strcpy(srRcpt.szStatusMessage, srLocSRec.szSettleResp);
            vdFormatSettleStatusMsg(srRcpt.szStatusMessage);
            inPrintReceiptHeader(pobTran);
            if (inPrintLines(&obPrinter, SETTLE_TOP_START, SETTLE_BOTTOM_END, NO_BL_LINE, lnMiddleCondition) != VS_SUCCESS)
                return(VS_ERR);
            lnMiddleCondition &= 0xEFFFFFFF;    /* Do not print report title but once   */
            for (lnRecNum += 1L; lnRecNum < 7L; lnRecNum++) {
                if (inLoadSettRec(pobTran, &srLocSRec, &srLocSKey, lnRecNum) == VS_SUCCESS) {
                    strlcpy(pobTran->szSettDate, &srLocSRec.szDate[4], 2);
                    strlcpy(&pobTran->szSettDate[2], srLocSRec.szDate, 4);
                    strlcpy(pobTran->szSettTime, srLocSRec.szTime, 6);
                    vdLoadDateTime(pobTran);
                    strcpy(srRcpt.szBatchNum, srLocSRec.szBatchNum);
                    pad(srRcpt.szBatchNum, srRcpt.szBatchNum, '0', inGetBatchNumSize(), RIGHT);
                    strcpy(srRcpt.szStatusMessage, srLocSRec.szSettleResp);
                    vdFormatSettleStatusMsg(srRcpt.szStatusMessage);

                    if (strcmp(srLocSRec.szDate, szDate) == 0) {
                        if (inPrintLines(&obPrinter, SETTLE_TOP_START, SETTLE_BOTTOM_END, NO_BL_LINE, lnMiddleCondition) != VS_SUCCESS)
                            return(VS_ERR);
                    }
                }
            }
            /* Prevent double printing status message */
            if (inPrintLines(&obPrinter, SETTLE_BOTTOM_END, SETTLE_BOTTOM_END, NO_BL_LINE, 0x04000000) != VS_SUCCESS)
                return(VS_ERR);
        }
        if (pobTran->szBatchNum[0] != '\0') {
            if (inGetBatchNumSettRec(pobTran, &srLocSRec, &srLocSKey) != VS_SUCCESS) {
                vdDisplayNoDataMsg();
                return(VS_SUCCESS);
            }
            strlcpy(pobTran->szSettDate, &srLocSRec.szDate[4], 2);
            strlcpy(&pobTran->szSettDate[2], srLocSRec.szDate, 4);
            strlcpy(pobTran->szSettTime, srLocSRec.szTime, 6);
            vdLoadDateTime(pobTran);
            strcpy(srRcpt.szBatchNum, srLocSRec.szBatchNum);
            pad(srRcpt.szBatchNum, srRcpt.szBatchNum, '0', inGetBatchNumSize(), RIGHT);
            /* Load Settle Response Message. */
            strcpy(srRcpt.szStatusMessage, srLocSRec.szSettleResp);
            vdFormatSettleStatusMsg(srRcpt.szStatusMessage);
            inPrintReceiptHeader(pobTran);
            lnMiddleCondition |= 0x04000000;    /* Eject paper after print */
            if (inPrintLines(&obPrinter, SETTLE_TOP_START, SETTLE_BOTTOM_END, NO_BL_LINE, lnMiddleCondition) != VS_SUCCESS)
                return(VS_ERR);
        }
    }
    vdSGErrorMessage(0L);
    return(VS_SUCCESS);
}

/*********************************************************************************************
* @func int | inPrintSettlementReport|
*       Base settlement function which calls sets the templates and the
*       condition flags and runs the form engine to print or reprint the
*       settlement report
*
* @parm TRANSACTION_OBJECT * | pobTran |
*       Transaction object.
*
* @rdesc return values.
* @flag int    |  VS_ERR
* @flag int    |  VS_SUCCESS
* @end
**********************************************************************************************/

int inPrintSettlementReport(TRANSACTION_OBJECT* pobTran,VS_BOOL fBatchReport,VS_BOOL fSettleSucceeded,VS_BOOL fCommErr) {
    char szTemplateFileName[FILENAME_SIZE + 1];

    //pdebug (("--inPrintSettlementReport--"));

    vdSGCode(SETTLE);
    if (inGetPrinterType() == NOPRINTER && fGetEnablePrinter()) {
        vdDisplayMessageFromFile(NO_PRINTER_MSG, WARNING_MSG);
        return(VS_SUCCESS);
    }

    if (!fGetEnablePrinter())
        return(VS_SUCCESS);

    /*
     *      if Not Batch History, Check HDT Flag for Settlement Report
     */
    if (fGetEnablePrinter())
        vdDisplayMessageFromFile(PRINTING_MSG, STATUS_MSG);

    strcpy(szTemplateFileName, STATIC_DATA_PATH);
    strcat(szTemplateFileName, szGetReport1NamePrefix());
    strcat(szTemplateFileName, szGetTemplateFileNameSuffix());

    if (inSwitchTemplate(szTemplateFileName) < 0) {
        vdDisplayMessageFromFile(FORMATER_ERR_MSG, ERROR_MSG);
        return(VS_ERR);
    }

    vdMakeReportHeader(pobTran);

    sprintf(srRcpt.szStatus2Message, SUBSTITUTE_D, inGetMerchantNum());

    vdSetSettleReportCondition(fBatchReport, fSettleSucceeded);
    if (!fSettleSucceeded && fCommErr)
        lnMiddleCondition |= 0x00400000;

    if (fBatchReport == VS_FALSE) {
        vdGGRespMsg(srRcpt.szStatusMessage);
        vdFormatSettleStatusMsg(srRcpt.szStatusMessage);
        if (inRunFormSegments(pobTran, SETTLE_REPORT) != VS_SUCCESS)
            return(VS_ERR);
    } else {
        if (inRunFormSegments(pobTran, REPRINT_SETTLE) != VS_SUCCESS)
            return(VS_ERR);
    }

    return(VS_SUCCESS);
}

/*********************************************************************************************
* @func int | inPrintSettleReport|
*       Form flow function which prints the settlement report
*
* @parm TRANSACTION_OBJECT * | pobTran |
*       Transaction object.
*
* @rdesc return values.
* @flag int    |  VS_ERR
* @flag int    |  VS_SUCCESS
* @end
**********************************************************************************************/

int inPrintSettleReport(TRANSACTION_OBJECT* pobTran) {
    inPrintReceiptHeader(pobTran);
    if (inPrintLines(&obPrinter, SETTLE_TOP_START, SETTLE_BOTTOM_END, NO_BL_LINE, lnMiddleCondition) != VS_SUCCESS)
        return(VS_ERR);
    return(VS_SUCCESS);
}

/*********************************************************************************************
* @func void | vdFormatSettleStatusMsg|
*       Form flow function which prints the settlement report
*
* @parm TRANSACTION_OBJECT * | pobTran |
*       Transaction object.
*
* @rdesc return values.
* @flag int    |  VS_ERR
* @flag int    |  VS_SUCCESS
* @end
**********************************************************************************************/

void vdFormatSettleStatusMsg(char* szStatusMessage) {
    if (inGetP350ColMode() == COLUMN_TYPE_24) {
        if (strlen(szStatusMessage) < 24)
            pad(szStatusMessage, szStatusMessage, ' ', 24, CENTER);
    }
}

int SETTLE_CODE_CHECK(char* a,char* b,short* c,char* d,unsigned char* e) {
    GET_VER(a, b, c, d, e);
    return 1;
}

/*********************************************************************************************
* @func void | vdDisplayNoDataMsg|
*       Displays msg "No Data - " + host name
*
* @parm TRANSACTION_OBJECT * | pobTran |
*       Transaction object.
*
* @rdesc return values - None.
* @end
**********************************************************************************************/
void vdDisplayNoDataMsg() {
    char szDummy[MESSAGE_SIZE];
    char szHostName[HOST_NAME_SIZE + 1];

    vdGetMessageFromFile(NO_SETT_DATA_MSG, szDummy);
    strcpy(szHostName, szGetHostName());

    strcat(szDummy, szHostName);
    vdDisplayMessage(szDummy, WARNING_MSG);
}



#undef VSSETL_C

#endif // BATCH_DEFINED
